package com.itrus.spring.inject.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;

@RestController
public class InjectFinalValueController {
    /**
     * 核心源码实现：
     * 扫描：
     * AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition -> findAutowiringMetadata -> buildAutowiringMetadata -> ReflectionUtils.doWithLocalFields
     * 注入：
     * AutowiredAnnotationBeanPostProcessor#postProcessProperties -> metadata.inject -> element.inject -> ReflectionUtils.makeAccessible(field); field.set(bean, value);
     *
     * 1. static 修饰的属性，在扫描的时候会被忽略
     * 2. final 修饰的属性，在扫描的时候不会被忽略，注入的时候也会注入成功
     * 3. final 修饰的基本类型和 String 类型，编译器会当做常量来使用，进行字面量替换。
     *     访问 /inject/finalValue 接口返回空，访问 /inject/reflectValue 返回 admin
     */

    @Value("${user.id}")
    private final String id = "";

    @Value("${user.id}")
    private static final String staticId = "";

    @RequestMapping(path = "/inject/finalValue")
    public String value() {
        return id;
    }

    @RequestMapping(path = "/inject/static/finalValue")
    public String staticValue() {
        return staticId;
    }

    @RequestMapping(path = "/inject/reflectValue")
    public String reflectValue() throws IllegalAccessException {
        Field idField = ReflectionUtils.findField(InjectFinalValueController.class, "id");
        return (String) idField.get(this);
    }


    @RequestMapping(path = "/inject/static/reflectValue")
    public String staticReflectValue() throws IllegalAccessException {
        Field staticIdField = ReflectionUtils.findField(InjectFinalValueController.class, "staticId");
        return (String) staticIdField.get(this);
    }
}